package com.jxzn.locust.controller.admin;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.excel.EasyExcel;
import com.jxzn.locust.dto.PlayerQueryDTO;
import com.jxzn.locust.dto.ResultDTO;
import com.jxzn.locust.model.Player;
import com.jxzn.locust.service.AbstractService;
import com.jxzn.locust.service.PlayerService;
import com.jxzn.locust.support.Auth;
import com.jxzn.locust.support.Module;
import com.jxzn.locust.support.OperateAction;

import net.sf.json.JSONObject;

@Controller
@RequestMapping("/bg/player")
@Module("程序员管理")
public class PlayerController extends NamedEntityController<Player> {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    PlayerService playerService;

    @Override
    public AbstractService<Player> getService() {
        return playerService;
    }

    @Override
    public String getFolder() {
        return "player";
    }

    @PostMapping("/select")
    @ResponseBody
    @Auth(action = OperateAction.VIEW)
    public ResultDTO<Page<Player>> selectList(PlayerQueryDTO param) {
        Specification<Player> spec = buildSpecification(param);
        Order order = Order.desc("createTime");
        Sort sort = Sort.by(order);
        Pageable pageable = PageRequest.of(param.getPageNo() - 1, param.getPageSize(), sort);
        Page<Player> page = playerService.findPage(spec, pageable);
        Player.showAll(page.getContent());
        return new ResultDTO<Page<Player>>(page);
    }

    @GetMapping("/export")
    @Auth(action = OperateAction.VIEW)
    public void export(HttpServletRequest request, HttpServletResponse response, PlayerQueryDTO param) throws IOException {

        Specification<Player> spec = buildSpecification(param);
        Order order = Order.desc("createTime");
        Sort sort = Sort.by(order);
        Pageable pageable = PageRequest.of(0, Integer.MAX_VALUE, sort);
        Page<Player> page = playerService.findPage(spec, pageable);
        List<Player> eList = page.getContent();
        Player.showAll(eList);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String name = "报名信息";
        String fileName;
        try {
            fileName = URLEncoder.encode(name, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), Player.class).sheet(name).doWrite(eList);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            JSONObject json = new JSONObject();
            json.put("status", "failure");
            json.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(json.toString());
        }
    }

    /**
     * 去编辑页面
     * 
     * @param model
     * @param id
     * @return
     */
    @GetMapping("/detail")
    @Auth(action = OperateAction.VIEW)
    public String edit(Model model, Player query, @RequestParam("id") int id) {
        String action = "添加";
        if (id > 0) {
            Optional<Player> optional = getService().findById(id);
            if (optional.isPresent()) {
                Player player = optional.get();
                player.show();
                model.addAttribute("target", player);
                action = "编辑";
            }
        }
        model.addAttribute("query", query);
        model.addAttribute("action", action);
        return "/bg/" + getFolder() + "/edit";
    }

    private Specification<Player> buildSpecification(PlayerQueryDTO param) {

        Specification<Player> spec = new Specification<Player>() {

            private static final long serialVersionUID = 1L;

            @Override
            public Predicate toPredicate(Root<Player> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> pList = new ArrayList<Predicate>();
                if (StringUtils.isNotBlank(param.getName())) {
                    pList.add(cb.like(root.get("name"), "%" + param.getName() + "%"));
                }
                if (StringUtils.isNotBlank(param.getMobile())) {
                    pList.add(cb.like(root.get("mobile"), "%" + param.getMobile() + "%"));
                }
                if (null != param.getDeleted()) {
                    pList.add(cb.equal(root.get("deleted"), param.getDeleted()));
                }
                if (null != param.getStartDate()) {
                    pList.add(cb.greaterThanOrEqualTo(root.get("createTime"), param.getStartDate()));
                }
                if (null != param.getEndDate()) {
                    pList.add(cb.lessThanOrEqualTo(root.get("createTime"), param.getEndDate()));
                }
                return cb.and(pList.toArray(new Predicate[0]));
            }
        };
        return spec;
    }

}
